import Roact from '@rbxts/roact';

interface MvvmEntity {
    /** 绑定对象 */
    obj?: NumberValue | StringValue,
    /** 文本显示格式化 */
    formater?: (arg: string | number) => string
    /** UIGradient 的 最高透明度 */
    maxTrans?: number
}

/**
 * 路由控制器
 */
export default class BaseComponent<P> {
    didMountFun: Array<() => void> = []
    didMount() {
        // throw new Error('Method not implemented.');
        this.didMountFun.forEach(c => {
            c()
        })
        this.didMountFun.clear()
    }
    connects: (RBXScriptConnection)[] = []
    public willUnmount(): void {
        this.connects.forEach(c => {
            c?.Disconnect();
        })
    }
    mvvm<T extends Instance>(entity: MvvmEntity) {
        const ref = Roact.createRef<T>()
        const f = (c: string | number) => {
            const refObj = ref.getValue() as Instance | undefined;
            if (refObj?.IsA('TextLabel') || refObj?.IsA('TextButton') || refObj?.IsA('TextBox')) {
                if (entity.formater) {
                    refObj.Text = entity.formater(c)
                } else {
                    refObj.Text = c + ''
                }

            } else if (refObj?.IsA('UIGradient')) {
                if (typeIs(c, 'number')) {
                    try {
                        const v = math.min(c, 0.999);
                        refObj.Transparency = new NumberSequence([
                            new NumberSequenceKeypoint(0, entity.maxTrans || 0),
                            new NumberSequenceKeypoint(v, entity.maxTrans || 0),
                            new NumberSequenceKeypoint(v + 0.001, 1),
                            new NumberSequenceKeypoint(1, 1)])
                    } catch {
                        // print('eooro----c', c)
                    }

                }

            }
        }
        if (entity.obj)
            this.connects.push(entity.obj.Changed.Connect(f))
        f('')
        this.didMountFun.push(() => {
            f(entity.obj?.Value || '')
        })
        task.delay(1, () => {
            f(entity.obj?.Value || '')
        })
        return ref
    }
    binded = false
    bind<T>(propBind: (keyof P)[], props: P, setState: (value: T) => void) {
        if (this.binded) {
            return
        }
        this.binded = true;
        this.connects?.forEach(c => {
            c?.Disconnect();
        })
        this.connects?.clear()
        propBind.forEach(name => {
            const kindsValue = props[name] as {
                Changed?: RBXScriptSignal<(value: T) => void>
            }
            if (typeIs(kindsValue, 'number') || typeIs(kindsValue, 'string')) return
            if (kindsValue?.Changed)
                this.connects.push(kindsValue.Changed.Connect((value: T) => {
                    setState(value)
                }))
        })

    }
}